﻿#include "videoplayer.h"
#include "porting.h"
//#include "sd_path_ff.h"
//#include "lcd.h"
//#include "ltdc.h"

#define longjmp(x,y)

#define MJPEG_MAX_MALLOC_SIZE 		38*1024

void* mjpeg_malloc(u32 num)
{
	u32 curpos=g_video_player->jmempos;
 	g_video_player->jmempos+=num;
	if(g_video_player->jmempos>MJPEG_MAX_MALLOC_SIZE)
	{
		//printf("mem error:%d,%d",curpos,num);
	}
	return (void *)&g_video_player->jmembuf[curpos];
}

static void my_error_exit(j_common_ptr cinfo)
{
	//my_error_ptr myerr=(my_error_ptr) cinfo->err;
	//(*cinfo->err->output_message) (cinfo);
	//longjmp(myerr->setjmp_buffer, 1);
}

METHODDEF(void) my_emit_message(j_common_ptr cinfo, int msg_level)
{
	//my_error_ptr myerr=(my_error_ptr) cinfo->err;
    //if(msg_level<0)
	//{
	//	longjmp(myerr->setjmp_buffer, 1);
	//}
}

static void init_source(j_decompress_ptr cinfo)
{
    return;
}

static boolean fill_input_buffer(j_decompress_ptr cinfo)
{
	if(g_video_player->jbufsize==0)
	{
        g_video_player->jpegbuf[0] = (u8) 0xFF;
        g_video_player->jpegbuf[1] = (u8) JPEG_EOI;
  		cinfo->src->next_input_byte =g_video_player->jpegbuf;
		cinfo->src->bytes_in_buffer = 2;
	}else
	{
		cinfo->src->next_input_byte =g_video_player->jpegbuf;
		cinfo->src->bytes_in_buffer = g_video_player->jbufsize;
	}
    return TRUE;
}

static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
    /* Just a dumb implementation for now.  Could use fseek() except
    * it doesn't work on pipes.  Not clear that being smart is worth
    * any trouble anyway --- large skips are infrequent.
    */
    if (num_bytes > 0)
    {
        while(num_bytes>(long) cinfo->src->bytes_in_buffer)
        {
            num_bytes-=(long)cinfo->src->bytes_in_buffer;
            (void)cinfo->src->fill_input_buffer(cinfo);
            /* note we assume that fill_input_buffer will never
            * return FALSE, so suspension need not be handled.
            */
        }
        cinfo->src->next_input_byte += (size_t) num_bytes;
        cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
    }
}
static void term_source(j_decompress_ptr cinfo)
{
    return;
}

static void jpeg_filerw_src_init(j_decompress_ptr cinfo)
{
    if (cinfo->src == NULL)     /* first time for this JPEG object? */
    {
        cinfo->src = (struct jpeg_source_mgr *)
                     (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                              sizeof(struct jpeg_source_mgr));
    }
    cinfo->src->init_source = init_source;
    cinfo->src->fill_input_buffer = fill_input_buffer;
    cinfo->src->skip_input_data = skip_input_data;
    cinfo->src->resync_to_restart = jpeg_resync_to_restart;/* use default method */
    cinfo->src->term_source = term_source;
    cinfo->src->bytes_in_buffer = 0;/* forces fill_input_buffer on first read */
    cinfo->src->next_input_byte = NULL;/* until buffer loaded */
}


u8 mjpegdec_init(u16 offx,u16 offy)
{
	g_video_player->cinfo=(struct jpeg_decompress_struct*)MALLOC(sizeof(struct jpeg_decompress_struct));
	g_video_player->jerr=(struct my_error_mgr*)MALLOC(sizeof(struct my_error_mgr));
	g_video_player->jmembuf=(u8*)MALLOC(MJPEG_MAX_MALLOC_SIZE);

	g_video_player->outrectbuf=(u16*)MALLOC(sizeof(u16)*lcddev_width*DRAW_LINES);
	if(g_video_player->cinfo==0||g_video_player->jerr==0||g_video_player->jmembuf==0||g_video_player->outrectbuf==0)
	{
		mjpegdec_free();
		return 1;
	}
	g_video_player->imgoffx=offx;
	g_video_player->imgoffy=offy;
	return 0;
}

void mjpegdec_free(void)
{
	FREE(g_video_player->cinfo);
	FREE(g_video_player->jerr);
	FREE(g_video_player->jmembuf);
	FREE(g_video_player->outrectbuf);
}

u8 mjpegdec_decode(u8* buf,u32 bsize)
{
    JSAMPARRAY buffer=0;
	if(bsize==0)
		return 1;
	g_video_player->jpegbuf=buf;
	g_video_player->jbufsize=bsize;
	g_video_player->jmempos=0;

	g_video_player->cinfo->err=jpeg_std_error(&g_video_player->jerr->pub);
	g_video_player->jerr->pub.error_exit = my_error_exit;
	g_video_player->jerr->pub.emit_message = my_emit_message;
	if(0)// (setjmp(jerr->setjmp_buffer))
	{
 		jpeg_abort_decompress(g_video_player->cinfo);
		jpeg_destroy_decompress(g_video_player->cinfo);
		return 2;
	}
	jpeg_create_decompress(g_video_player->cinfo);
	jpeg_filerw_src_init(g_video_player->cinfo);
	jpeg_read_header(g_video_player->cinfo, TRUE);
	g_video_player->cinfo->dct_method = JDCT_IFAST;
	g_video_player->cinfo->do_fancy_upsampling = 0;
	jpeg_start_decompress(g_video_player->cinfo);

	g_video_player->outlinecnt=g_video_player->imgoffy;

	while (g_video_player->cinfo->output_scanline < g_video_player->cinfo->output_height)
	{
		jpeg_read_scanlines(g_video_player->cinfo, buffer, 1);
	}

	jpeg_finish_decompress(g_video_player->cinfo);
	jpeg_destroy_decompress(g_video_player->cinfo);
	return 0;
}
